package com.lk.client.discovery;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.lk.client.loadbanlance.Route;
import com.lk.client.loadbanlance.RouteStrategy;
import com.lk.dto.ResponseResult;
import com.lk.entity.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 服务发现
 *
 * @author kun.li
 */
@Component
public class SeviceDiscovery {

    @Autowired
    private NamicServiceConfig namicServiceConfig;

    /**
     * 本地缓存的注册中心列表
     */
    private final static Map<String, Set<Service>> localMap = new ConcurrentHashMap<>();

    /**
     * 更新的注册列表
     */
    private final static Map<String, Set<Service>> updateMap = new ConcurrentHashMap<>();


    // 初始化时先获取一次注册列表
    @PostConstruct
    public void init() {
        Map<String, Set<Service>> serviceAll = getServiceAll();
        localMap.putAll(serviceAll);
        // 启动定时拉取注册列表
        timingJob();
    }

    public void timingJob() {
        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1, new ThreadPoolExecutor.CallerRunsPolicy());
        scheduledThreadPoolExecutor.scheduleWithFixedDelay(() -> {
            Map<String, Set<Service>> map = getServiceAll();
            if (MapUtil.isEmpty(updateMap)) {
                updateMap.putAll(map);
            } else if (MapUtil.isNotEmpty(updateMap)) {
                localMap.putAll(updateMap);
            }

        }, 1000, 5000, TimeUnit.MILLISECONDS);
    }

    private Map<String, Set<Service>> getServiceAll() {
        String get = HttpUtil.get(namicServiceConfig.getAddress() + "/register");
        ResponseResult responseResult = JSONUtil.toBean(get, ResponseResult.class);
        Map<String, Set<Service>> map = new HashMap<>();
        if (responseResult.getCode() == 0) {
            Object data = responseResult.getData();
            JSONObject jsonObject = new JSONObject(data);
            for (Map.Entry<String, Object> entry : jsonObject) {
                Object value = entry.getValue();
                JSONArray jsonArray = new JSONArray(value);
                Set<Service> serviceSet = new HashSet<>();
                for (Object o : jsonArray) {
                    Service service = JSONUtil.toBean(new JSONObject(o), Service.class);
                    serviceSet.add(service);
                }
                map.put(entry.getKey(), serviceSet);
            }
        }
        return map;
    }

    public static Service getService(String serviceName) {
        Set<Service> serviceSet = localMap.get(serviceName);
        if (CollUtil.isNotEmpty(serviceSet)) {
            Route route = RouteStrategy.getRoute(RouteStrategy.RANDOM.name);
            return route.switchService(serviceSet);
        }
        throw new IllegalArgumentException("不存在");
    }


}
